--
--  Copyright 2022 The Open Islands Authors. All Rights Reserved.
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
--
local _M = {
    _VERSION = '0.1'
}

local ngx = ngx
local utils = require "utils"
local config = require "config"
local dns_utils = require "dns_utils"
local string = string
local log = require("log")
local constant = require("constant")

local api_version = "v1"

function _M.query_route(env)
    local res = _M.request_apiserver("/apiserver/v1/routes/"..env)
    if res and res["code"] == 0 then
        return res["data"]
    elseif res then
        log.error("query ", env, " services from apiserver failed, msg: ", res["message"])
    else
        log.error("query ", env, " services from apiserver no response")
    end
    return nil
end

function _M.get_node_service_address(service_name)
    local service_config
    if service_name == constant.APISERVER then
        service_config = config.apiserver
    elseif service_name == constant.MASTER then
        service_config = config.master
    elseif service_name == constant.WORKER then
        service_config = config.worker
    else
        return nil, nil, "no "..service_name.." service"
    end
    local tls_enabled = false
    local ip, err = dns_utils.get_ip_address(service_config["host"])
    if ip == nil then
        err = "get "..service_config.." address using domain: "..service_config["host"].." by dns failed"
        log.error(err)
        return nil, nil, err
    end
    local port
    if ngx.req.http_version() == 2 then
        port = service_config["grpc_port"]
    else
        port = service_config["http_port"]
    end
    return ip ..":"..tostring(port), tls_enabled, err
end

function _M.request_apiserver(endpoint, body)
    return _M.send_request(_M.get_node_service_address(constant.APISERVER), endpoint, body)
end

function _M.request_master(endpoint, body)
    return _M.send_request(_M.get_node_service_address(constant.MASTER), endpoint, body)
end

function _M.request_worker(endpoint, body)
    return _M.send_request(_M.get_node_service_address(constant.WORKER), endpoint, body)
end

function _M.send_request(address, endpoint, body)
    local url = string.format("http://%s%s", address, endpoint)
    local headers = {["Content-Type"] = "application/json;charset=utf8"}
    local res
    if body == nil then
        res = utils.http_client(url, "GET", nil, headers, config.federatedproxy["http_tries"], 200)
    else
        res = utils.http_client(url, "POST", utils.json_dumps(body), headers, config.federatedproxy["http_tries"], 200)
    end
    if res and res.status == 200 then
        return utils.json_loads(res.body)
    elseif res then
        log.error("request url: ", url, " failed, status code: ", res.status)
        return nil
    else
        return nil
    end
end

return _M